package strategy;

import java.util.List;

import com.stibocatalog.hunspell.Hunspell;

import windows.MainWindow;

import core.CharCount;
import core.OpenedFile;

public class KeywordCaesar implements AlgorithmInteface {

	private char[] abc;
	private String text;
	private String keyword;
	private String result;
	private int k;
	private int resultK;
	private int abcLenght;
//	private String fileName;
	
	private char[] autoCodedAbc;
	
	private char[] abc_statistic = Crypto.ENG_ABC_STAT;
	private MainWindow ref;
	

    private String getRealKeyword(String keyword){
        String newKeyWord = "";
        char[] key = keyword.toCharArray();
        
        for(int i=0;i<key.length;i++){
            if(!newKeyWord.contains(Character.toString(key[i]))){
                newKeyWord = newKeyWord + Character.toString(key[i]);
            }
        }
        
        return newKeyWord;
    }
	
	public KeywordCaesar(String text, String keyword, int k,int language, MainWindow reference) {
		this.text = text;
		this.keyword = keyword;
		this.k = k;
		ref = reference;
		
		switch (language) {
		case 0:
			System.out.println("English dictionary loaded!");
			abc = Crypto.ENG_ABC;
			abcLenght = Crypto.ENG_LEGHT;
			break;
		case 1:
			System.out.println("English dictionary loaded!");
			abc = Crypto.HUN_ABC;
			abcLenght = Crypto.HUN_LEGHT;
			break;
		default:
			new Exception("No such language!");
		}
	}
	
	public KeywordCaesar(String text, int language, MainWindow reference) {
//		this.fileName = fileName;
		this.text = text;
		ref = reference;
		switch (language) {
		case 0:
			System.out.println("English dictionary loaded!");
			abc = Crypto.ENG_ABC;
			abcLenght = Crypto.ENG_LEGHT;
			break;
		case 1:
			System.out.println("English dictionary loaded!");
			abc = Crypto.HUN_ABC;
			abcLenght = Crypto.HUN_LEGHT;
			break;
		default:
			new Exception("No such language!");
		}
	}

	private boolean contains(char[] chars, char c) {
		boolean cont = false;

		for (int i = 0; i < chars.length; i++) {
			if (c == chars[i])
				return true;
		}

		return cont;
	}
	
	private char[] createPerm(int tol) {
		char[] codedAbc = new char[abcLenght];

		k = tol;
		int index = k;
		char[] nKw = getRealKeyword(keyword).toCharArray();

		for (int i = 0; i < nKw.length; i++) {
			codedAbc[index] = nKw[i];
			index++;
		}
		
		int i = 0;
		while (index < abcLenght && i < abcLenght) {
			if (!contains(codedAbc, abc[i])) {
				codedAbc[index] = abc[i];
				index++;
			}
			i++;
		}
		
		index = 0;
		while (index < k && i < abcLenght) {
			if (!contains(codedAbc, abc[i])) {
				codedAbc[index] = abc[i]; // tomb a kodolt abc-vel
				index++;
			}
			i++;
		}
		return codedAbc;
		
	}
	
	private String createResult(char[] codedAbc) {
		result = "";
		char[] inp = text.toCharArray();
		for (int ind = 0; ind < inp.length; ind++) {
			boolean found = false;
			for (int j = 0; j < abc.length; j++) {
				if (inp[ind] == abc[j]) {
					result = result + codedAbc[j];
					found = true;
				} else {
					if (inp[ind] == Character.toUpperCase(abc[j])) {
						result = result + Character.toUpperCase(codedAbc[j]);
						found = true;
					}
				}
			}

			// ha nem talalt megfelelo betut, akkor ugyan ugy irja
			if (!found) {
				result = result + inp[ind];
			}
		}
		
		return result;
	}

	public String createResult2(char[] abc) {
		result = "";
		char[] inp = text.toCharArray();
		
		for (int ind = 0; ind < inp.length; ind++) {
			boolean found = false;
			for (int j = 0; j < abc.length; j++) {
				if (inp[ind] == Character.toLowerCase(abc[j])) {
					result = result + autoCodedAbc[j];
					found = true;
				} else {
					if (inp[ind] == Character.toUpperCase(abc[j])) {
						result = result + Character.toUpperCase(autoCodedAbc[j]);
						found = true;
					}
				}
			}

			// ha nem talalt megfelelo betut, akkor ugyan ugy irja
			if (!found) {
				if ((Character.toLowerCase(inp[ind]) >= 'a') && (Character.toLowerCase(inp[ind]) <= 'z')) {
					result = result + '*';
				}
				else {
					result = result + inp[ind];
				}
			}
		}
		
		return result;
	}
	
	@Override
	public void decrypt() {
		
		char[] codedAbc = createPerm(k);
		resultK = k;
		char[] temp = abc;
		abc = codedAbc;
		codedAbc = temp;
		
		result = createResult(codedAbc);
		
		autoCodedAbc = codedAbc;
		
		update();
		
//		result = "";
//		char[] inp = text.toCharArray();
//		for (int ind = 0; ind < inp.length; ind++) {
//			boolean found = false;
//			for (int j = 0; j < abc.length; j++) {
//				if (inp[ind] == abc[j]) {
//					result = result + codedAbc[j];
//					found = true;
//				} else {
//					if (inp[ind] == Character.toUpperCase(abc[j])) {
//						result = result + Character.toUpperCase(codedAbc[j]);
//						found = true;
//					}
//				}
//			}
//
//			// ha nem talalt megfelelo betut, akkor ugyan ugy irja
//			if (!found) {
//				result = result + inp[ind];
//			}
//		}
	}

	@Override
	public void encrypt() {
	
		char[] codedAbc = createPerm(k);
		resultK = k;
		result = createResult(codedAbc);
		
		autoCodedAbc = abc;
		abc = codedAbc;
		
		update();
		
//		result = "";
//		char[] inp = text.toCharArray();
//		for (int ind = 0; ind < inp.length; ind++) {
//			boolean found = false;
//			for (int j = 0; j < abc.length; j++) {
//				if (inp[ind] == abc[j]) {
//					result = result + codedAbc[j];
//					found = true;
//				} else if (inp[ind] == Character.toUpperCase(abc[j])) {
//					result = result + Character.toUpperCase(codedAbc[j]);
//					found = true;
//				}
//			}
//
//			// ha nem talalt megfelelo betut, akkor ugyan ugy irja
//			if (!found) {
//				result = result + inp[ind];
//			}
//		}
	}

	@Override
	public void update() {
		ref.keywordCaesarUpdate(autoCodedAbc, abc, result, resultK, keyword);
	}
	
	public String getResult() {
		return result;
	}
	
	public String toString() {
		return result;
	}

	@Override
	public void autoDecrypt() {
		autoCodedAbc = new char[abcLenght];
		
//		OpenedFile.getInstance().setNewFile(fileName);
		
//		text = OpenedFile.getInstance().toString();
		
		KeyStatistic ks = new KeyStatistic(text);
		List<CharCount> stat = ks.sort();
		
		for (int i = 0; i < abcLenght; i++) {
			autoCodedAbc[i] =  '*';
		}
		
		for (int i = 0; i < 5; i++) {
			autoCodedAbc[i] =  stat.get(i).get_c();
		}
		
		autoCodedAbc[10] =  stat.get(10).get_c();
		autoCodedAbc[11] =  stat.get(11).get_c();
		
//		codedAbc[4] = 'D';
//		codedAbc[5] = 'K';
//		codedAbc[6] = 'Q';
//		codedAbc[7] = 'B';
//		codedAbc[3] = 'L';
//		codedAbc[8] = '*';
//		codedAbc[11] = 'N';
//		codedAbc[19] = 'Z';
		
		for (int i = 0; i < abcLenght; i++) {
			for (int j = 0; j < abcLenght; j++) {
				if (abc_statistic[i] < abc_statistic[j]) {
					char c = abc_statistic[i];
					abc_statistic[i] = abc_statistic[j];
					abc_statistic[j] = c;
					
					c = autoCodedAbc[i];
					autoCodedAbc[i] = autoCodedAbc[j];
					autoCodedAbc[j] = c;
				}
			}
		}
		
//		codedAbc[5] = 'E';
//		codedAbc[6] = 'A';
//		codedAbc[9] = 'F';
//		codedAbc[10] = 'G';
//		codedAbc[11] = 'H';
//		codedAbc[12] = 'J';
//		codedAbc[15] = 'M';
		
		
		System.out.println(abc_statistic);
		System.out.println(autoCodedAbc);
		
		abc = abc_statistic;
		
		char[] temp = abc;
		abc = autoCodedAbc;
		autoCodedAbc = temp;
		
		result = "";
		char[] inp = text.toCharArray();
		
		for (int ind = 0; ind < inp.length; ind++) {
			boolean found = false;
			for (int j = 0; j < abc.length; j++) {
				if (inp[ind] == Character.toLowerCase(abc[j])) {
					result = result + autoCodedAbc[j];
					found = true;
				} else {
					if (inp[ind] == Character.toUpperCase(abc[j])) {
						result = result + Character.toUpperCase(autoCodedAbc[j]);
						found = true;
					}
				}
			}

			// ha nem talalt megfelelo betut, akkor ugyan ugy irja
			if (!found) {
				if ((Character.toLowerCase(inp[ind]) >= 'a') && (Character.toLowerCase(inp[ind]) <= 'z')) {
					result = result + '*';
				}
				else {
					result = result + inp[ind];
				}
			}
		}
		
		System.out.println(result);
		System.out.println(text);
		
		update();
	}
	
	public void setCodedAbc(char[] abc) {
		this.abc = abc;
		createResult2(abc);
		update();
	}


}
